{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cb6be12",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import yfinance as yf\n",
    "from utils import plot_returns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3292b3a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Download front-month futures data of S&P500, 10-year Treasuries, gold and US dollar\n",
    "symbols = ['ES=F', 'ZN=F', 'GC=F', 'DX=F']\n",
    "data = yf.download(symbols)\n",
    "# Resample data so that we deal with monthly data instead of daily to reduce noise\n",
    "data = data.resample(\"M\").last()\n",
    "data.index = pd.to_datetime(data.index)\n",
    "# Subset adjusted close prices and fill NaNs with value know at time t\n",
    "# Drop rows with unknown prices in the beginning of the dataset\n",
    "prices = data[\"Adj Close\"].ffill().dropna()\n",
    "prices.index = pd.to_datetime(prices.index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26225531",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compute logarithmic returns\n",
    "log_returns = np.log(prices).diff()\n",
    "# Compute risk parity weights\n",
    "annual_vol = log_returns.std() * np.sqrt(12)\n",
    "inverse_vol = 1 / annual_vol\n",
    "risk_parity_weights = inverse_vol / inverse_vol.sum()\n",
    "weighted_returns = (log_returns * risk_parity_weights).sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3ad47784",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Annualize returns and volatility\n",
    "annualized_return = weighted_returns.mean() * 12\n",
    "annualized_vol = weighted_returns.std() * np.sqrt(12)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "559ae89f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calculate the Sharpe Ratio\n",
    "sharpe_ratio = annualized_return / annualized_vol\n",
    "# Calculate the Sortino Ratio\n",
    "downside_vol = weighted_returns[weighted_returns<0].std() * np.sqrt(12)\n",
    "sortino_ratio = annualized_return / downside_vol\n",
    "# Calculate the Calmar Ratio\n",
    "cum_returns = np.exp(weighted_returns.cumsum())\n",
    "drawdowns = (cum_returns.cummax() - cum_returns) / cum_returns.cummax()\n",
    "max_drawdown = np.max(drawdowns)\n",
    "calmar_ratio = annualized_return / max_drawdown"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f55b8feb",
   "metadata": {},
   "outputs": [],
   "source": [
    "print()\n",
    "print(f\"annualized_return: {np.round(annualized_return * 100, 1)}%\")\n",
    "print(f\"annualized_volatility: {np.round(annualized_vol * 100, 1)}%\")\n",
    "print(f\"downside_volatility: {np.round(downside_vol * 100, 1)}%\")\n",
    "print(f\"max_drawdown: {np.round(max_drawdown * 100, 1)}%\")\n",
    "print()\n",
    "print(f\"sharpe_ratio: {np.round(sharpe_ratio, 2)}\")\n",
    "print(f\"sortino_ratio: {np.round(sortino_ratio, 2)}\")\n",
    "print(f\"calmar_ratio: {np.round(calmar_ratio, 2)}\")\n",
    "print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72ad82c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_returns(weighted_returns)"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
